"""
基础命令类

提供所有CLI命令的基础功能。
"""

import click
from abc import ABC, abstractmethod
from typing import Dict, List, Optional, Any

from ...utils.logger import get_module_logger
from ...utils.es_client import ESClient
from ...config.settings import Settings


class BaseCommand(ABC):
    """基础命令类
    
    所有CLI命令的基类，提供通用功能。
    """
    
    def __init__(self, config: Settings, debug_mode: bool = False):
        """初始化基础命令

        Args:
            config: 配置对象
            debug_mode: 是否启用调试模式
        """
        self.config = config
        self.debug_mode = debug_mode
        self.logger = get_module_logger(self.__class__.__name__)
        self._es_client = None

    @property
    def es_client(self) -> ESClient:
        """获取ES客户端（懒加载）"""
        if self._es_client is None:
            self._es_client = ESClient(
                self.config.config.elasticsearch.model_dump(),
                debug_mode=self.debug_mode
            )
        return self._es_client
    
    def validate_index_exists(self, index: str) -> bool:
        """验证索引是否存在
        
        Args:
            index: 索引名称
            
        Returns:
            是否存在
        """
        try:
            return self.es_client.index_exists(index)
        except Exception as e:
            self.logger.error(f"检查索引存在性失败: {index}, {e}")
            return False
    
    def format_size(self, size_bytes: int) -> str:
        """格式化文件大小
        
        Args:
            size_bytes: 字节数
            
        Returns:
            格式化的大小字符串
        """
        from ...utils.file_utils import format_size
        return format_size(size_bytes)
    
    def format_duration(self, seconds: float) -> str:
        """格式化持续时间
        
        Args:
            seconds: 秒数
            
        Returns:
            格式化的时间字符串
        """
        if seconds < 60:
            return f"{seconds:.1f}秒"
        elif seconds < 3600:
            minutes = seconds / 60
            return f"{minutes:.1f}分钟"
        else:
            hours = seconds / 3600
            return f"{hours:.1f}小时"
    
    def print_table(self, headers: List[str], rows: List[List[str]], title: Optional[str] = None):
        """打印表格
        
        Args:
            headers: 表头
            rows: 数据行
            title: 表格标题
        """
        if title:
            click.echo(f"\n{title}")
            click.echo("=" * len(title))
        
        if not rows:
            click.echo("没有数据")
            return
        
        # 计算列宽
        col_widths = [len(header) for header in headers]
        for row in rows:
            for i, cell in enumerate(row):
                if i < len(col_widths):
                    col_widths[i] = max(col_widths[i], len(str(cell)))
        
        # 打印表头
        header_line = " | ".join(
            header.ljust(col_widths[i]) for i, header in enumerate(headers)
        )
        click.echo(f"\n{header_line}")
        click.echo("-" * len(header_line))
        
        # 打印数据行
        for row in rows:
            row_line = " | ".join(
                str(cell).ljust(col_widths[i]) for i, cell in enumerate(row)
            )
            click.echo(row_line)
        
        click.echo()
    
    def print_json(self, data: Any, indent: int = 2):
        """打印JSON格式数据
        
        Args:
            data: 要打印的数据
            indent: 缩进空格数
        """
        import json
        click.echo(json.dumps(data, indent=indent, ensure_ascii=False, default=str))
    
    def print_yaml(self, data: Any):
        """打印YAML格式数据
        
        Args:
            data: 要打印的数据
        """
        try:
            import yaml
            click.echo(yaml.dump(data, default_flow_style=False, allow_unicode=True))
        except ImportError:
            click.echo("错误: 需要安装PyYAML库才能输出YAML格式")
            self.print_json(data)
    
    def confirm_action(self, message: str, default: bool = False) -> bool:
        """确认操作
        
        Args:
            message: 确认消息
            default: 默认值
            
        Returns:
            用户确认结果
        """
        return click.confirm(message, default=default)
    
    def show_progress(self, iterable, label: str = "处理中", length: Optional[int] = None):
        """显示进度条
        
        Args:
            iterable: 可迭代对象
            label: 进度标签
            length: 总长度
            
        Returns:
            带进度条的迭代器
        """
        return click.progressbar(iterable, label=label, length=length)
    
    def echo_success(self, message: str):
        """输出成功消息
        
        Args:
            message: 消息内容
        """
        click.echo(click.style(f"✓ {message}", fg='green'))
    
    def echo_warning(self, message: str):
        """输出警告消息
        
        Args:
            message: 消息内容
        """
        click.echo(click.style(f"⚠ {message}", fg='yellow'))
    
    def echo_error(self, message: str):
        """输出错误消息
        
        Args:
            message: 消息内容
        """
        click.echo(click.style(f"✗ {message}", fg='red'))
    
    def echo_info(self, message: str):
        """输出信息消息
        
        Args:
            message: 消息内容
        """
        click.echo(click.style(f"ℹ {message}", fg='blue'))
    
    def handle_keyboard_interrupt(self):
        """处理键盘中断"""
        click.echo("\n操作被用户中断", err=True)
        raise click.Abort()
    
    def validate_parameters(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """验证参数
        
        Args:
            params: 参数字典
            
        Returns:
            验证后的参数
        """
        # 子类可以重写此方法来实现特定的参数验证
        return params
    
    @abstractmethod
    def execute(self, *args, **kwargs) -> Any:
        """执行命令
        
        子类必须实现此方法。
        """
        pass
